﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace Needle.Bus.Transport.Impl.WCF.Hosts
{
    public class WCFSingletonServiceHost<T> : ServiceHost
    {

        public WCFSingletonServiceHost(string topic)
            : base(new WCFEndPoint<T>(topic))
        {
            if (String.IsNullOrEmpty(topic))
                throw new ArgumentException("topic is null or empty.", "topic");
            _Topic = topic;
        }

        private readonly string _Topic;
        public string Topic
        {
            get { return _Topic; }
        }

        public WCFEndPoint<T> Singleton
        {
            get { return (WCFEndPoint<T>)SingletonInstance; }
        }

        protected override ServiceDescription CreateDescription(out IDictionary<string, ContractDescription> implementedContracts)
        {
            var contract = ContractDescription.GetContract(typeof(IChannel<T>));
            var binding = WCFSettings.Binding;
            var address = WCFSettings.Address<T>(Singleton.Topic);
            var serviceEndpoint = new ServiceEndpoint(contract, binding, address);
            serviceEndpoint.Name = Singleton.Topic;

            var serviceBehaviour = new ServiceBehaviorAttribute();
            serviceBehaviour.ConcurrencyMode = ConcurrencyMode.Multiple;
            serviceBehaviour.InstanceContextMode = InstanceContextMode.Single;
            serviceBehaviour.UseSynchronizationContext = false;
            serviceBehaviour.SetWellKnownSingleton(Singleton);

            var serviceDescription = new ServiceDescription();
            serviceDescription.Name = Singleton.Topic;
            serviceDescription.Namespace = Constants.NeedleBusNamespace;
            serviceDescription.Endpoints.Add(serviceEndpoint);
            serviceDescription.Behaviors.Add(serviceBehaviour);
            serviceDescription.ConfigurationName = Singleton.Topic;

            var contracts = new Dictionary<string, ContractDescription>();
            contracts.Add(Singleton.Topic, contract);
            implementedContracts = contracts;
            return serviceDescription;
        }
    }
}
